package com.qmscy.sparrow.common.filter;

import com.qmscy.sparrow.common.constant.AssertMessage;
import com.qmscy.sparrow.common.constant.Constant;
import com.qmscy.sparrow.config.properties.JwtProperties;
import com.qmscy.sparrow.plugin.jwt.TokenGenerator;
import io.jsonwebtoken.Claims;
import java.io.IOException;
import java.util.Collections;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.Assert;

/**
 * @Author: wangxiaonan
 * @Date: 2019/1/7
 **/
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {

    private static final Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);

    private JwtProperties jwtProperties;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager, JwtProperties jwtProperties) {
        super(authenticationManager);
        this.jwtProperties = jwtProperties;

    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String rawToken = request.getHeader(Constant.RESPONSE_HEADER_AUTHORIZATION);

        // 判断token是否存在
        if (StringUtils.isBlank(rawToken) || !rawToken.startsWith(jwtProperties.getHeader())) {
            chain.doFilter(request, response);
            return;
        }

        UsernamePasswordAuthenticationToken authenticationToken = parseToken(rawToken);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken parseToken(String rawToken) {
        Assert.notNull(rawToken, AssertMessage.NOT_NULL_PARAM);
        String token = rawToken
                .replace(String.format(Constant.RESPONSE_BEARER_REPLACE_STRING, jwtProperties.getHeader()), "");

        Claims claims = TokenGenerator.parse(token, jwtProperties.getSecret());

        String username = claims.getAudience();
        if (StringUtils.isBlank(username)) {
            return null;
        }

        return new UsernamePasswordAuthenticationToken(username, null,
                Collections.singleton(new SimpleGrantedAuthority("")));
    }
}
